#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "KRWS.h"
#include "StringTokenizer.h"
#include "StringTrim.h"
#include "Node.h"
#include "NodeArray.h"
#include "dastrie.h"
#define _DEBUG_MODE_
using namespace std;

vector<string> _VLines;

string reverse(string key)
{
    string tmp ="";

    int i;

    for( i= 0;i< (int)key.length(); i= i+3)
    {
        tmp = key.substr( i, 3) + tmp;
    }

    return tmp;
}

void read_txt(string fileName)
{
    uint16_t    rec_cnt=0;;
    int flag;
    string line;
    ifstream fin ( fileName.c_str() );
    if( fin == NULL)
    {
        cout << "Input file is NOT opened!!\n";
        exit(1);
    }

    cout << "Reading records in txt file.\n";
    while( !fin.eof() )
    {
        getline( fin, line );

        line = StringTrim::trim( line );

        if( line.length() <= 0) continue;
        if( line.substr(0,1) =="#") continue;
     
        flag = -1;
        flag = line.find(":",0);

        if( flag == -1) continue;

        _VLines.push_back( reverse( line.substr( 0, flag) ) + line.substr(  flag, line.length() - flag) );

        rec_cnt ++;

        if( (rec_cnt % 1000 ) == 0) cout <<".";
#ifdef _DEBUG_MODE_
        if( rec_cnt > 10) break;
#endif
    }

    sort( _VLines.begin(), _VLines.end());
/*
    for( int i =0 ; i< _VLines.size();i++)
    {
        cout << _VLines[i] << endl;
    }
*/
    fin.close();
}


uint8_t find_pos_id( string &pos )
{
    int i;

    for(i=0;i<_POS_SIZE_;i++)
    {
       if( pos == _KRWS_POS[ i] )
           return (uint8_t)i;
    }

    return 0;
}

int main( int argc, char *argv[])
{
#ifdef _DEBUG_MODE_
    int cnt=0;
#endif

    uint32_t rec_cnt=0,i;
    int  line_cnt;
    string line;

    // trie의 record를 정의한다. record는 key, value로 구성되어 있고,
    // key는 string, value는 NODE **로 구성된다.
    // NODE**인 이유는 하나의 단어(string)이 하나 이상의 POS로 구성되기 때문이다.
    typedef dastrie::builder<std::string,   Node_array   > builder_type;

    // trie를 지정한다
    // trie는 위의 NODE **와 동일하다.
    typedef dastrie::trie< Node_array  > trie_type;

    // 하나의 record를 편하게 사용하기 위해 정의
    typedef builder_type::record_type record_type;


    // 반드시 명령어 + 입력파일 + 출력파일 형태로 실행
    if( argc != 3 )
    {
        cout << "./build_dict input_txt_name dict_name\n";
        exit(1);
    }


    // dict file을 open
    // format은 string:POS1_ID:POS1_Freq:POS2_ID:POS2_fre....
    ifstream fin(  argv[1] );
    // 읽은 line을 tokenize한 데이터를 저장
    vector< string >  VToken;

    // 읽은 data를 저장할 vector
    vector< record_type > VRecords;

    //VRecords에 넣을 임시 record
    record_type rec_tmp;

    Node_array VNode;

    if( fin == NULL)
    {
        cout <<"error, "<< argv[1] <<" is NOT OPEN\n";
        exit(1);
    }

    read_txt( argv[1] );

    Node node;
    cout << "\nBuilding dicts in step1.\n";

    for( line_cnt=0; line_cnt<(int)_VLines.size(); line_cnt++)
    {
        // line을 tokenize
        VToken.clear();
        StringTokenizer::tokenize(_VLines[ line_cnt ] , VToken ,":");

        rec_tmp.key = VToken[0] ;


        cout << VToken[0]  <<":";
        for(i=1;i< VToken.size();i=i+2)
        {
            node.pos = find_pos_id( VToken[i]  );
            node.freq = atol( VToken[i+1].c_str() );
 //           rec_tmp.value.setValue( find_pos_id( VToken[i]  ) , atol( VToken[i+1].c_str() ) );
 //           rec_tmp.value.push_back( VToken[i] );
            rec_tmp.value.push_back( node );

            cout <<  (int) node.pos <<":" << (int) node.freq<<"\n";;

        }
        cout << endl;



        VRecords.push_back( rec_tmp );

        rec_cnt++;
        if( (rec_cnt % 1000 ) == 0) cout <<".";

#ifdef _DEBUG_MODE_
#endif
    }


    try {
        builder_type builder;
        //builder.build(records, records + sizeof(records)/sizeof(records[0]));
        builder.build(& VRecords[0], &VRecords[  VRecords.size() -1 ]  ) ;

        std::ofstream ofs( argv[2]  , std::ios::binary);
        builder.write(ofs);
        ofs.close();
    } catch( const builder_type::exception& e) {
        std::cerr << "ERROR: " << e.what() << std::endl;
        return 1;
    }



    fin.close();










    std::ifstream ifs("post-word-tags.dict", std::ios::binary);
    if (ifs.fail()) 
    {
        std::cerr << "ERROR: Failed to open a trie file." << std::endl;
        return 1;
    }
    trie_type trie;

  if (trie.read(ifs) == 0) {
        std::cerr << "ERROR: Failed to read a trie file." << std::endl;
        return 1;
    }
    Node_array VTmp;
    trie.find("가", VTmp);


    for( int h=0;h< VTmp.size();h++)
    {
        cout <<(int) VTmp[h].pos <<":"<< (int) VTmp[h].freq <<"\n";
    }





    return 0;
}
